package com.qilin.hscs.service.impl;

import com.alibaba.fastjson.JSON;
import com.qilin.hscs.dto.UserDto;
import com.qilin.hscs.dto.UserModifyPassDto;
import com.qilin.hscs.enums.UserHostUsingStatus;
import com.qilin.hscs.enums.UserStatusEnum;
import com.qilin.hscs.pojo.MqttUser;
import com.qilin.hscs.pojo.User;
import com.qilin.hscs.enums.ResultEnum;
import com.qilin.hscs.exception.SMException;
import com.qilin.hscs.pojo.UserHost;
import com.qilin.hscs.repository.MqttUserRepository;
import com.qilin.hscs.repository.UserHostRepository;
import com.qilin.hscs.service.UserService;
import com.qilin.hscs.repository.UserRepository;
import com.qilin.hscs.strategy.SaltGenerationStrategy;
import com.qilin.hscs.util.MD5Util;
import com.qilin.hscs.util.ResultVOUntil;
import com.qilin.hscs.util.TokenUtil;
import com.qilin.hscs.vo.ResultVO;
import com.qilin.hscs.vo.UserVO;
import org.apache.commons.collections.ListUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository repository;

    @Autowired
    private UserHostRepository userHostRepository;

    @Autowired
    private MqttUserRepository mqttUserRepository;

    private static final Logger logger= LogManager.getLogger(UserServiceImpl.class.getName());


    @Override
    public ResultVO register(User user) {
        User user1=repository.findByPhone(user.getPhone());
        if(user1!=null){
            throw new SMException(ResultEnum.USER_IS_REGISTER);
        }
        String salt = SaltGenerationStrategy.generate(user);
        String md5Pass = null;
        md5Pass = MD5Util.encrypt(user.getPassword(), salt);
        user.setPassword(md5Pass);
        user.setSalt(salt);
        User save = repository.save(user);
        if (save != null) {
            MqttUser mqttUser=new MqttUser();
            mqttUser.setPassword(save.getPassword());
            mqttUser.setSalt(save.getSalt());
            mqttUser.setUsername(save.getPhone());
            mqttUserRepository.save(mqttUser);
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(save,userVO);
            return ResultVOUntil.success(userVO);
        }
       return null;
    }

    @Override
    public ResultVO loginByPass(String username,String password) {
        //登陆可以通过多种方式
        //1 通过密码的方式
        //todo 以后还可以用邮箱登陆
        User user = findOneByPhone(username);
        //用户处于锁定状态
        if (user.getStatus() == UserStatusEnum.LOCKED.getStatus()) {
            throw new SMException(ResultEnum.ACCOUNT_LOCKED);
        }
        //密码不正确
        if (!MD5Util.verify(user.getPassword(), password, user.getSalt())) {
            throw new SMException(ResultEnum.LOGIN_FAILD);
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);

        //登陆成功后返回token 作为登陆的凭证 一切需要在登陆状态下才能做的操作都需要在头部加入token 用来验证登陆
        Map<String, Object> subjectobj = new HashMap<>(1);
        subjectobj.put("username", username);
        String token = TokenUtil.create(JSON.toJSONString(subjectobj));
        userVO.setToken(token);
        return ResultVOUntil.success(userVO);
    }

    @Override
    public ResultVO findUserByPhone(String phone) {
        User user = findOneByPhone(phone);
        UserVO userVO=new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return ResultVOUntil.success(userVO);
    }

    @Override
    public ResultVO ModifyUserInfo(UserDto userDto) {
        User user = findOneByPhone(userDto.getPhone());
        BeanUtils.copyProperties(userDto, user);
        User save = repository.save(user);
        UserVO userVO=new UserVO();
        BeanUtils.copyProperties(save, userVO);
        return ResultVOUntil.success(userVO);
    }

    @Override
    public ResultVO updatePassword(UserModifyPassDto dto) {
            User user = findOneByPhone(dto.getPhone());
            String md5Pass = MD5Util.encrypt(dto.getPassword(), user.getSalt());
            user.setPassword(md5Pass);
            repository.save(user);
            return ResultVOUntil.success();
    }

    @Override
    public User findOneByPhone(String phone) {
        User user = repository.findByPhone(phone);
        if (user == null) {
            throw new SMException(ResultEnum.USER_NOT_FOUND);
        }
        return user;
    }
}